package kz.pompei.ifacer.util;

import java.util.Iterator;

public abstract class KillingList<H> implements Iterable<H> {
  private static class Node<H> {
    Node<H> next, prev;
    H value;
  }
  
  private Node<H> first = null;
  
  public Killer add(H handler) {
    final Node<H> node = new Node<>();
    node.value = handler;
    
    if (first == null) {
      first = node.next = node.prev = node;
    } else {
      node.next = first;
      node.prev = first.prev;
      
      first.prev.next = node;
      first.prev = node;
    }
    
    return new Killer() {
      @Override
      public void kill() {
        killNode(node);
      }
    };
  }
  
  @Override
  public Iterator<H> iterator() {
    return new Iterator<H>() {
      Node<H> current = first;
      boolean isFirst = true;
      
      @Override
      public boolean hasNext() {
        if (first == null) return false;
        if (current == null) return false;
        if (isFirst) return true;
        return current != first;
      }
      
      @Override
      public H next() {
        H ret = current.value;
        current = current.next;
        isFirst = false;
        return ret;
      }
      
      @Override
      public void remove() {
        throw new UnsupportedOperationException();
      }
    };
  }
  
  private void killNode(final Node<H> node) {
    if (node.next == node) {
      first = null;
      return;
    }
    
    node.prev.next = node.next;
    node.next.prev = node.prev;
    
    if (first == node) first = first.next;
  }
}
